package com.mmall.concurrency.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 概述：
 * CyclicBarrier 同步辅助类。允许一组线程相互等待，知道到达一个公共的屏障点。
 * 通过它可以完成多个线程之间相互等待。只有当每一个线程都准备就绪后，才能各自继续往下执行后面的操作。
 * 和CountDownLatch相似，都是通过计数器来实现的。
 * 当调用await方法后，该线程进入等待状态，计数器执行+1操作。
 * 当计数器达到设置的初始值时，因为调用await方法而进行等待的线程会被唤醒，继续执行后续的操作。
 * 因为count可以重复使用（使用reset重置），因此又称CyclicBarrier为循环屏障。
 *
 * 与CountDownLatch区别：
 * 1.CyclicBarrier的计数器可以重复使用，而CountDownLatch的计数器只能使用一次。
 * 2.
 * CyclicBarrier是实现了多个线程之间相互等待，直到所有线程都符合条件之后，才能继续往下执行，描述了各个线程内部相互等待的关系。
 * CountDownLatch是实现一个或多个线程需要等待其他线程完成操作以后，才能继续往下执行，描述了一个或多个线程等待其他线程之间的关系。
 *
 * 应用场景：
 * 可以应用多线程计算数据，最后合并计算结果的应用场景(自己制作的统计绩效的应用，可以用CyclicBarrier，多线程计算不同
 * 分组的绩效总和，然后合并计算公司所有人员的总绩效)
 */
@Slf4j
public class CyclicBarrierExample1 {

    private static CyclicBarrier barrier = new CyclicBarrier(5);

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        barrier.await();
        log.info("{} continue", threadNum);
    }
}
